Attribute VB_Name = "Utilities"
Function insertSort(iArray As Variant, inLow As Integer, inHi As Integer, keyNo As Integer)

Dim i As Integer, j As Integer
Dim tmpSwap As Object

For i = inLow + 1 To inHi
    Set tmpSwap = iArray(i)
    For j = i To inLow + 1 Step -1
        If iArray(j - 1).compkey(keyNo) > tmpSwap.compkey(keyNo) Then
            Set iArray(j) = iArray(j - 1)
        Else
            Exit For
        End If
    Next j
    Set iArray(j) = tmpSwap
Next i

End Function
Function insertSortTxtObj(iArray As Variant, inLow As Integer, inHi As Integer, keyNo As Integer)

Dim i As Integer, j As Integer
Dim tmpSwap As Object

For i = inLow + 1 To inHi
    Set tmpSwap = iArray(i)
    For j = i To inLow + 1 Step -1
        If StrComp(iArray(j - 1).compkey(keyNo), tmpSwap.compkey(keyNo)) > 0 Then
            Set iArray(j) = iArray(j - 1)
        Else
            Exit For
        End If
    Next j
    Set iArray(j) = tmpSwap
Next i

End Function
Function insertSortRev(iArray As Variant, inLow As Integer, inHi As Integer, keyNo As Integer)

Dim i As Integer, j As Integer
Dim tmpSwap As Object

For i = inLow + 1 To inHi
    Set tmpSwap = iArray(i)
    For j = i To inLow + 1 Step -1
        If iArray(j - 1).compkey(keyNo) < tmpSwap.compkey(keyNo) Then
            Set iArray(j) = iArray(j - 1)
        Else
            Exit For
        End If
    Next j
    Set iArray(j) = tmpSwap
Next i

End Function
Sub quickSort(iArray As Variant, inLow As Integer, inHi As Integer, keyNo As Integer)
      
  'iArray()   The array to sort
  'inLow      Lower bound of sort point
  'inHi       Upper bound of sort point
      
  'Dim two working variables to hold
  'array members. The first holds the
  'pivot item - the item half way between
  'the inLow and inHi values, while the
  'second is used to hold the array contents
  'that will be swapped later.
  'These two items should be declared as
  'the same data type as the array passed.
   Dim pivot   As Object
   Dim tmpSwap As Object
   
  'Dim two working variables to hold the
  'values representing the pivot's lower
  'and upper points as passed to the routine.
  'These should be declared as the same data
  'type as the inLow/inHi variables passed.
   Dim tmpLow  As Integer
   Dim tmpHi   As Integer
   
    
  'Save to the working variables the
  'values passed as lower & upper
   tmpLow = inLow
   tmpHi = inHi
    
  'Get the item halfway through the data
  'determined by the range passed as lower
  'and upper and assign it as the pivot data
  '
  'When first calling this routine the
  'range is inLow = LBound(array), and
  'inHi = UBound(array). During subsequent
  'calls, inLow and inHi will receive
  'different values as determined below.
   Set pivot = iArray((inLow + inHi) \ 2)
  'With pivot holding the value of the item
  'halfway through the range, compare the
  'rank of tmpLow to tmpHi and assign the two
  'tmp storage variables that data for later
  'comparison. Here we're continuing the loop
  'while the low item being compared value (tmpLow)
  'is less than tmpHi (the upper bound value).
   While (tmpLow <= tmpHi)
  
     'Since (and while) tmpLow remains less than
     'tmpHi, compare the value of the array()
     'element at this position against pivot.
      While (iArray(tmpLow).compkey(keyNo) < pivot.compkey(keyNo) And tmpLow < inHi)
         tmpLow = tmpLow + 1
      Wend
      
     'repeat the same for the array value at
     'position tmpHi.
      While (pivot.compkey(keyNo) < iArray(tmpHi).compkey(keyNo) And tmpHi > inLow)
         tmpHi = tmpHi - 1
      Wend

     'When the position of tmpHi exceeds or matches tmpLow
     'swap the two items.
      If (tmpLow <= tmpHi) Then
      
        'a: assign iArray(tmpLow) to tmpSwap
        'b: swap iArray(tmpHi) for iArray(tmpLow)
        'c: assign tmpSwap back to iArray(tmpHi)
         Set tmpSwap = iArray(tmpLow)
         Set iArray(tmpLow) = iArray(tmpHi)
         Set iArray(tmpHi) = tmpSwap
         
        'adjust the new Hi and Low values
         tmpLow = tmpLow + 1
         tmpHi = tmpHi - 1
      End If
   
   Wend
  
  'if the original lower is less than tmpHi,
  'call the routine again with inLow & tmpHi
  'as the pivot's lower and upper points.
   If (inLow < tmpHi) Then quickSort iArray, inLow, tmpHi, keyNo
   
  'if the new tmpLow value lower is less than
  'the original inHi, call the routine again with
  'tmpLow & inHi as the pivot's lower and upper points.
   If (tmpLow < inHi) Then quickSort iArray, tmpLow, inHi, keyNo
  
End Sub
Sub quickSortTxtObj(iArray As Variant, inLow As Integer, inHi As Integer, keyNo As Integer)
      
  'iArray()   The array to sort
  'inLow      Lower bound of sort point
  'inHi       Upper bound of sort point
      
  'Dim two working variables to hold
  'array members. The first holds the
  'pivot item - the item half way between
  'the inLow and inHi values, while the
  'second is used to hold the array contents
  'that will be swapped later.
  'These two items should be declared as
  'the same data type as the array passed.
   Dim pivot   As Object
   Dim tmpSwap As Object
   
  'Dim two working variables to hold the
  'values representing the pivot's lower
  'and upper points as passed to the routine.
  'These should be declared as the same data
  'type as the inLow/inHi variables passed.
   Dim tmpLow  As Integer
   Dim tmpHi   As Integer
   
    
  'Save to the working variables the
  'values passed as lower & upper
   tmpLow = inLow
   tmpHi = inHi
    
  'Get the item halfway through the data
  'determined by the range passed as lower
  'and upper and assign it as the pivot data
  '
  'When first calling this routine the
  'range is inLow = LBound(array), and
  'inHi = UBound(array). During subsequent
  'calls, inLow and inHi will receive
  'different values as determined below.
   Set pivot = iArray((inLow + inHi) \ 2)
  'With pivot holding the value of the item
  'halfway through the range, compare the
  'rank of tmpLow to tmpHi and assign the two
  'tmp storage variables that data for later
  'comparison. Here we're continuing the loop
  'while the low item being compared value (tmpLow)
  'is less than tmpHi (the upper bound value).
   While (tmpLow <= tmpHi)
  
     'Since (and while) tmpLow remains less than
     'tmpHi, compare the value of the array()
     'element at this position against pivot.
     'While (iArray(tmpLow).compkey(keyNo) < pivot.compkey(keyNo) And tmpLow < inHi)
      While (StrComp(iArray(tmpLow).compkey(keyNo), pivot.compkey(keyNo)) < 0 And tmpLow < inHi)
         tmpLow = tmpLow + 1
      Wend
      
     'repeat the same for the array value at
     'position tmpHi.
     'While (pivot.compkey(keyNo) < iArray(tmpHi).compkey(keyNo) And tmpHi > inLow)
      While (StrComp(pivot.compkey(keyNo), iArray(tmpHi).compkey(keyNo)) < 0 And tmpHi > inLow)
         tmpHi = tmpHi - 1
      Wend

     'When the position of tmpHi exceeds or matches tmpLow
     'swap the two items.
      If (tmpLow <= tmpHi) Then
      
        'a: assign iArray(tmpLow) to tmpSwap
        'b: swap iArray(tmpHi) for iArray(tmpLow)
        'c: assign tmpSwap back to iArray(tmpHi)
         Set tmpSwap = iArray(tmpLow)
         Set iArray(tmpLow) = iArray(tmpHi)
         Set iArray(tmpHi) = tmpSwap
         
        'adjust the new Hi and Low values
         tmpLow = tmpLow + 1
         tmpHi = tmpHi - 1
      End If
   
   Wend
  
  'if the original lower is less than tmpHi,
  'call the routine again with inLow & tmpHi
  'as the pivot's lower and upper points.
   If (inLow < tmpHi) Then quickSortTxtObj iArray, inLow, tmpHi, keyNo
   
  'if the new tmpLow value lower is less than
  'the original inHi, call the routine again with
  'tmpLow & inHi as the pivot's lower and upper points.
   If (tmpLow < inHi) Then quickSortTxtObj iArray, tmpLow, inHi, keyNo
  
End Sub
Function binSearchObj(keyNo As Integer, srchObj As Object, srchArray As Variant, dup1st As Boolean) As Integer

Dim low As Integer, high As Integer, found As Integer, try As Integer
Dim srchCompVal As Variant
Dim i As Integer

low = 1
high = UBound(srchArray)

Do While low <= high
    try = (low + high) \ 2
    testv1 = srchArray(try).compkey(keyNo)
    testv2 = srchObj.compkey(keyNo)
    srchCompVal = srchObj.compkey(keyNo) - srchArray(try).compkey(keyNo)
    If srchCompVal = 0 Then
        binSearchObj = try
        Exit Do
    ElseIf srchCompVal > 0 Then
        low = try + 1
    Else
        high = try - 1
    End If
Loop ' low <= high

If low > high Then
    binSearchObj = -1
Else
    
    If dup1st Then
        For i = binSearchObj - 1 To 1 Step -1
            If srchArray(i).compkey(keyNo) = srchObj.compkey(keyNo) Then
                binSearchObj = i
            Else
                Exit Function
            End If
        Next i
    Else
        For i = binSearchObj + 1 To UBound(srchArray)
            If srchArray(i).compkey(keyNo) = srchObj.compkey(keyNo) Then
                binSearchObj = i
            Else
                Exit Function
            End If
        Next i
    End If
End If


End Function
Function binSearchTxtObj(keyNo As Integer, srchTxt As String, srchArray As Variant, _
                                                    Optional low As Integer = 1, Optional high As Integer) As Integer

Dim try As Integer
Dim compVal As Integer
Dim i As Integer

If high = 0 Then
    high = UBound(srchArray)
End If

binSearchTxtObj = -1

Do While low <= high
    try = (low + high) \ 2
    compVal = StrComp(srchTxt, srchArray(try).compkey(keyNo))
    If compVal = 0 Then
        binSearchTxtObj = try
        Exit Do
    ElseIf compVal > 0 Then
        low = try + 1
    Else
        high = try - 1
    End If
Loop


End Function
Function binAreaSrchObj(keyNo As Integer, srchObj As Object, srchArray As Variant, dup1st As Boolean, upOrDn As Integer, _
                                                                   Optional l As Integer, Optional h As Integer) As Integer

Dim low As Integer, high As Integer, found As Integer, try As Integer
Dim keyVal As Variant
Dim i As Integer

If l > 0 Then
    low = l
Else
    low = 1
End If
If h > 0 Then
    high = h
Else
    high = UBound(srchArray)
End If

Do While low <= high
    try = (low + high) \ 2
    If srchObj.compkey(keyNo) = srchArray(try).compkey(keyNo) Then
        binAreaSrchObj = try
        GoTo adjust4Dups
    ElseIf srchObj.compkey(keyNo) > srchArray(try).compkey(keyNo) Then
        low = try + 1
    Else
        high = try - 1
    End If
Loop

keyVal = srchObj.compkey(keyNo) - srchArray(try).compkey(keyNo)
If keyVal > 0 Then
    If try = h Then
        binAreaSrchObj = try
    ElseIf upOrDn = -1 Then
        binAreaSrchObj = try
    ElseIf upOrDn = 1 Then
        binAreaSrchObj = try + 1
    ElseIf Abs(keyVal) <= Abs(srchObj.compkey(keyNo) - srchArray(try + 1).compkey(keyNo)) Then
        binAreaSrchObj = try
    Else
        binAreaSrchObj = try + 1
    End If
Else
    If try = l Then
        binAreaSrchObj = try
    ElseIf upOrDn = 1 Then
        binAreaSrchObj = try
    ElseIf upOrDn = -1 Then
        binAreaSrchObj = try - 1
    ElseIf Abs(keyVal) < Abs(srchObj.compkey(keyNo) - srchArray(try - 1).compkey(keyNo)) Then
        binAreaSrchObj = try
    Else
        binAreaSrchObj = try - 1
    End If
End If

adjust4Dups:

If dup1st Then
    For i = binAreaSrchObj - 1 To low Step -1
        If srchArray(i).compkey(keyNo) = srchArray(binAreaSrchObj).compkey(keyNo) Then
            binAreaSrchObj = i
        Else
            Exit Function
        End If
    Next i

Else
    For i = binAreaSrchObj + 1 To high
        If srchArray(i).compkey(keyNo) = srchArray(binAreaSrchObj).compkey(keyNo) Then
            binAreaSrchObj = i
        Else
            Exit Function
        End If
    Next i
End If


End Function
Function binRangeSrchTxtObj(keyNo As Integer, srchTxt As String, srchArray As Variant, _
                                                                   Optional low As Integer = 1, Optional high As Integer) As Integer()

Dim matchedRange(2) As Integer
Dim try As Integer
Dim compVal As Integer
Dim i As Integer

If high = 0 Then
    high = UBound(srchArray)
End If

Do While low <= high
    try = (low + high) \ 2
    compVal = StrComp(srchTxt, srchArray(try).compkey(keyNo))
    If compVal = 0 Then
        matchedRange(1) = try
        matchedRange(2) = try
        GoTo adjust4Dups
    ElseIf compVal > 0 Then
        low = try + 1
    Else
        high = try - 1
    End If
Loop ' low <= high


matchedRange(1) = -1
matchedRange(2) = -1
binRangeSrchTxtObj = matchedRange
Exit Function

adjust4Dups:
For i = matchedRange(1) - 1 To low Step -1
    If StrComp(srchArray(i).compkey(keyNo), srchArray(matchedRange(1)).compkey(keyNo)) = 0 Then
        matchedRange(1) = i
    Else
        Exit For
    End If
Next i
For i = matchedRange(2) + 1 To high
    If StrComp(srchArray(i).compkey(keyNo), srchArray(matchedRange(2)).compkey(keyNo)) = 0 Then
        matchedRange(2) = i
    Else
        Exit For
    End If
Next i

binRangeSrchTxtObj = matchedRange

End Function
Function binSearchTxt(srchText As String, srchArray() As String) As Integer

Dim low As Integer, high As Integer, found As Integer, try As Integer
Dim compVal As Integer


low = 1
high = UBound(srchArray)

While low <= high
    try = (low + high) \ 2
    compVal = StrComp(srchText, srchArray(try))
    If compVal = 0 Then
        binSearchTxt = try
        Exit Function
    ElseIf compVal > 0 Then
        low = try + 1
    Else
        high = try - 1
    End If
Wend ' low <= high

binSearchTxt = -1

End Function
Function parseStr(s As String, begTkn As String, endTkn As String, startCh As Integer) As String

Dim begCh As Integer, endCh As Integer

begCh = InStr(startCh, s, begTkn) + 1
If begCh < 2 Then
    parseStr = ""
    Exit Function
End If
endCh = InStr(begCh + 1, s, endTkn) - 1
If endCh < 0 Then
    parseStr = ""
    Exit Function
End If
parseStr = Mid$(s, begCh, endCh - begCh + 1)

End Function

